home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 23
/
CU Amiga - Super CD-ROM 23 (June 1998).iso
/
CUCD
/
Magazine
/
C_Tutorial
/
Part-11
/
req1.bak
/
fractal.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-04-05
|
3KB
|
122 lines
#include "fractal.h"
#include<exec/tasks.h>
#include<stdlib.h>
#include<stdio.h>
#include "gadgets.h"
#include<clib/alib_protos.h>
#include<clib/exec_protos.h>
#include<clib/graphics_protos.h>
static int calc(double, double, int);
static void fractal(void);
/* The mechanism by which we will control our task: */
/* One Semaphore for drawing, the other for running */
static struct SignalSemaphore drawing;
static struct SignalSemaphore running;
/* Initialisation done when program is started */
void initSemaphores()
{
InitSemaphore(&drawing);
InitSemaphore(&running);
}
/* To stop the fractal we stop it drawing then stop our */
/* task from running */
void stopFractal()
{
ObtainSemaphore(&drawing);
ObtainSemaphore(&running);
ReleaseSemaphore(&running);
ReleaseSemaphore(&drawing);
}
/* A local copy of the window pointer for our task */
static struct Window* win;
/* Draw a fractal in the window */
void drawFractal(struct Window* w)
{
/* If the semaphore is available a task is not already running */
if(AttemptSemaphore(&running))
{
struct Task* task;
ReleaseSemaphore(&running);
/* Make a copy of the window pointer for the task to use */
win = w;
/* Create a new task which will draw the fractal */
task = CreateTask("HelloPainter-Fractal",-1,&fractal,4096);
if(task == NULL)
printf("Error: could not create task\n");
}
else
/* The semaphore was already taken, so stop the task */
stopFractal();
}
/* The starting point of our task */
static void __saveds fractal()
{
/* If the semaphore is available we can start running */
if(AttemptSemaphore(&running))
{
/* The width, height and number of colours for drawing */
int w=win->Width, h=win->Height, d=1<<win->WScreen->BitMap.Depth;
/* The snapshot of the mandelbrot set to draw */
/* (Adjust these numbers to draw different fractals) */
double width=4.0, height=4.0, top=-2.0, left=-2.5;
double* array = malloc(h*sizeof(double));
if(array)
{
int x;
/* Load the array with the vertical values */
for(x=0; x<h; x++)
array[x]=x*height/h+top;
/* Check whether we can continue drawing on each x */
for(x=0; x<w && AttemptSemaphore(&drawing); x++)
{
/* Precalculate the horizontal value */
double xr = x*width/w+left;
int y;
for(y=0; y<h; y++)
{
/* Set the current colour, using our precalculated values */
setFgPen(win, calc(xr,array[y],d));
/* Draw the pixel */
WritePixel(win->RPort,x,y);
}
/* Release the semaphore before checking again */
ReleaseSemaphore(&drawing);
}
/* Now we've finished, release the memory from the malloc()ed array */
free(array);
}
/* Release the semaphore to indicate the task has finished */
ReleaseSemaphore(&running);
}
}
/* Calculate the colour of a particular point */
/* (This is the number of iterations of the equation */
/* needed to exceed the bound value) */
static int calc(double x, double y, int d)
{
double xc=x, yc=y;
double xsq=x*x, ysq=y*y;
int it;
/* Adjust the 16.0 to give different colour spreads */
for(it=0; it<d && xsq+ysq<16.0; it++)
{
yc = 2.0*xc*yc+y;
xc = xsq-ysq+x;
xsq = xc*xc;
ysq = yc*yc;
}
return it;
}